package adminapp

import (
	"gitee.com/captials-team/ubdframe/src/apps"
	httpController "gitee.com/captials-team/ubdframe/src/apps/adminapp/controllers/http"
	"gitee.com/captials-team/ubdframe/src/apps/adminapp/docs"
	"gitee.com/captials-team/ubdframe/src/common"
	"gitee.com/captials-team/ubdframe/src/common/utils"
	"gitee.com/captials-team/ubdframe/src/domain/configstc"
	"gitee.com/captials-team/ubdframe/src/domain/interfaces"
	"gitee.com/captials-team/ubdframe/src/pkg/gin_http"
	"gitee.com/captials-team/ubdframe/src/pkg/jwtauth"
	v1log "gitee.com/captials-team/ubdframe/src/pkg/logs"
	"github.com/gin-gonic/gin"
	"go.uber.org/dig"
)

type ApiServer struct {
	*apps.ApiServer

	di   *dig.Scope
	conf *configstc.AdminAppConfig

	gin_http.AuthOption           //认证相关选项配置
	gin_http.SwaggerOption        //swagger相关选项配置
	gin_http.PProfOption          //pprof选项配置
	gin_http.OperateLogOption     //操作日志
	gin_http.AuthExtendInfoOption //认证扩展信息选项配置
	gin_http.AccreditOption       //授权选项
}

func (s *ApiServer) Name() string {
	return "admin_api"
}

func (s *ApiServer) InitRouter() {
	s.Engine().GET("ping", gin_http.PingHandler)
	s.InitRouterForGin(s.Engine())
}

func (s *ApiServer) router(g gin.IRouter) {
	g.Use(
		gin_http.PanicHandler,
		gin_http.QPSLimiterHandler(10, 10),
	)
	authGroup := g.Group("", s.OptAuthHandler(), s.OptAccreditHandler())

	common.ErrPanic(s.di.Invoke(func(ctr interfaces.ItfAdminAuthController, captcha interfaces.ItfCaptchaController) {
		if d, ok := ctr.(*httpController.AuthController); ok {
			d.AuthExtendInfoOption = s.AuthExtendInfoOption
		}
	}))

	common.ErrPanic(s.di.Invoke(func(ctr interfaces.ItfAdminAuthController, captcha interfaces.ItfCaptchaController) {
		//验证码
		g.POST("/mag/captcha/get", captcha.GetCaptcha) //图片验证码

		//登陆相关
		g.POST("/mag/auth/login", captcha.VerifyHandler(), ctr.AuthLogin, s.RecordLog("登录")) //不需要授权
		authGroup.POST("/mag/auth/check", ctr.AuthCheck)
		authGroup.POST("/mag/auth/info", ctr.AuthInfo)
		authGroup.POST("/mag/auth/logout", ctr.AuthLogout, s.RecordLog("登出"))
		authGroup.POST("/mag/auth/fresh_token", ctr.AuthFreshToken)
	}))

	//个人中心
	common.ErrPanic(s.di.Invoke(func(ctr interfaces.ItfAdminCenterController) {
		authGroup.POST("/mag/u_center/info", ctr.UserInfo)                                  //个人信息
		authGroup.POST("/mag/u_center/modify_pwd", ctr.ModifyPassword, s.RecordLog("修改密码")) //修改密码（登录情况下）
		authGroup.POST("/mag/u_center/modify_info", ctr.ModifyInfo, s.RecordLog("修改个人信息"))
	}))

	common.ErrPanic(s.di.Invoke(func(ctr interfaces.ItfAccreditController) {
		authGroup.POST("/mag/u_center/accredit_info", ctr.AccreditInfo)
	}))

	//管理员管理
	common.ErrPanic(s.di.Invoke(func(ctr interfaces.ItfAdminManageController) {
		//管理员管理
		authGroup.POST("/mag/admin/search", ctr.SearchAdmin, s.RecordLog("进入管理员管理"))
		authGroup.POST("/mag/admin/detail", ctr.QueryAdmin, s.RecordLog("查看管理员"))
		authGroup.POST("/mag/admin/save", ctr.SaveAdmin, s.RecordLog("创建/更新管理员"))
		authGroup.POST("/mag/admin/disable", ctr.DisableAdmin, s.RecordLog("禁用管理员"))
		authGroup.POST("/mag/admin/delete", ctr.DeleteAdmin, s.RecordLog("删除管理员"))
	}))

	//管理员日志
	common.ErrPanic(s.di.Invoke(func(ctr interfaces.ItfAdminLogController) {
		//管理员管理
		authGroup.POST("/mag/admin_log/search", ctr.SearchAdminLog, s.RecordLog("进入日志管理"))
	}))

	//权限管理（RBAC）
	common.ErrPanic(s.di.Invoke(func(ctr interfaces.ItfRbacManageController) {
		//rbac-用户角色信息
		authGroup.POST("/mag/rbac/user/role/search", ctr.SearchUserRoles)
		authGroup.POST("/mag/rbac/user/role/bind", ctr.BindUserRoles, s.RecordLog("绑定用户角色"))

		//rbac-角色
		authGroup.POST("/mag/rbac/role/search", ctr.SearchRoles, s.RecordLog("进入角色管理"))
		authGroup.POST("/mag/rbac/role/simples", ctr.SimpleRoles) //简易返回所有角色
		authGroup.POST("/mag/rbac/role/detail", ctr.QueryRole, s.RecordLog("查看角色详情"))
		authGroup.POST("/mag/rbac/role/save", ctr.SaveRole, s.RecordLog("新增/更新角色信息"))
		authGroup.POST("/mag/rbac/role/disable", ctr.DisableRole, s.RecordLog("启用/禁用角色"))
		authGroup.POST("/mag/rbac/role/delete", ctr.DeleteRole, s.RecordLog("删除角色"))
		authGroup.POST("/mag/rbac/role/permissions", ctr.SearchRolePermissions)
		authGroup.POST("/mag/rbac/role/permission/save", ctr.SaveRolePermissions, s.RecordLog("更新角色权限"))

		//rbac-权限
		authGroup.POST("/mag/rbac/permission/search", ctr.SearchPermissions, s.RecordLog("进入权限树管理"))
		authGroup.POST("/mag/rbac/permission/save", ctr.SavePermission, s.RecordLog("新增/更新权限树节点"))
		authGroup.POST("/mag/rbac/permission/delete", ctr.DeletePermission, s.RecordLog("删除权限树节点"))
	}))
	//组织管理
	common.ErrPanic(s.di.Invoke(func(ctr interfaces.ItfOrganizeManageController) {
		authGroup.POST("/mag/organize/search", ctr.SearchOrganize, s.RecordLog("进入组织管理"))
		authGroup.POST("/mag/organize/tree", ctr.TreeOrganize) //简易返回组织树
		authGroup.POST("/mag/organize/detail", ctr.QueryOrganize, s.RecordLog("查看组织详情"))
		authGroup.POST("/mag/organize/save", ctr.SaveOrganize, s.RecordLog("新增/更新组织信息"))
		authGroup.POST("/mag/organize/disable", ctr.DisableOrganize, s.RecordLog("启用/禁用组织"))
		authGroup.POST("/mag/organize/delete", ctr.DeleteOrganize, s.RecordLog("删除组织"))
	}))
}

func (s *ApiServer) InitRouterForGin(engine *gin.Engine) {
	var g = engine.Group("")
	if len(s.conf.RoutePrefix) > 0 {
		g = engine.Group(s.conf.RoutePrefix)
	}

	//注册swagger
	s.SwaggerRouter(g)

	//注册pprof
	s.PProfRouter(engine)

	s.router(g)

	return
}

func (s *ApiServer) Start() error {
	if !s.Module() {
		s.InitRouter()
	}
	return s.ApiServer.Start()
}

func (s *ApiServer) Stop() error {
	return s.ApiServer.Stop()
}

func NewApiServer(di *dig.Scope, conf *configstc.AdminAppConfig, logger v1log.ILog) *ApiServer {

	//swagger配置，取值后取指针是为了实现复用（多App）
	swaggerDocs := *docs.SwaggerInfoadminservice
	swaggerDocs.Host = conf.ApiServer.HostAddr() + utils.KeepHasPrefix(conf.RoutePrefix, "/")

	s := &ApiServer{
		di:   di,
		conf: conf,
		SwaggerOption: gin_http.SwaggerOption{
			Enable:  conf.DocsEnable,
			Name:    swaggerDocs.InstanceName(),
			Swagger: &swaggerDocs,
		},
		PProfOption: gin_http.PProfOption{
			Enable: conf.PProfEnable,
		},
		ApiServer: apps.NewApiServer(gin.Default(), conf.ApiServer),
	}

	s.WithName(conf.Name)
	s.WithCors() //开启跨域设置

	s.AuthOption.AuthHandler = gin_http.AuthHandler(jwtauth.NewJwtTokenHandler(conf.AuthConfig.SecretKey))

	common.ErrPanic(s.di.Invoke(func(ctr interfaces.ItfAdminLogController) {
		s.OperateLogOption.OperateLogHandler = ctr.LogHandler()
	}))

	return s
}
